﻿using System;
using MugenInjection.Infrastructure;
using MugenInjection.Interface;
#if !NOEXPRESSION
using System.Linq.Expressions;
#endif

namespace MugenInjection.Syntax.Type
{
    /// <summary>
    /// Specific fluent syntax for type binding.
    /// </summary>
    public interface ITypeConstructorSyntax : IBindingBuilder
    {
        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <param name="types">The specified parameters for search constructor.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor(params System.Type[] types);

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T1>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T1, T2>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T1, T2, T3>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T1, T2, T3, T4>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T1, T2, T3, T4, T5>();
    }

    /// <summary>
    /// Specific fluent syntax for type binding.
    /// </summary>
    public interface ITypeConstructorSyntax<T> : IBindingBuilder
    {
        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <param name="types">The specified parameters for search constructor.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T> TakeConstructor(params System.Type[] types);

#if NOEXPRESSION
        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T> TakeConstructor<T1>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T> TakeConstructor<T1, T2>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T> TakeConstructor<T1, T2, T3>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T> TakeConstructor<T1, T2, T3, T4>();

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T> TakeConstructor<T1, T2, T3, T4, T5>();
#else
        /// <summary>
        /// Indicates that the service should be bound to the specified constructor
        /// </summary>
        /// <param name="constructor">The constructor expression.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T> TakeConstructor(Expression<Func<ResolveContext, T>> constructor);
#endif
    }
}